CI: add SwiftPM iOS e2e workflows (RNTester, HelloWorld, new app) - #57659
CI: add SwiftPM iOS e2e workflows (RNTester, HelloWorld, new app)#57659chrfalch wants to merge 11 commits into
Conversation
Adds three standalone workflows that scaffold + convert an iOS app to
SwiftPM using the prebuilt XCFrameworks and compile it:
- test-ios-spm-rntester.yml (packages/rn-tester)
- test-ios-spm-helloworld.yml (private/helloworld)
- test-ios-spm-newapp.yml (fresh copy of helloworld, wired to a
Verdaccio-published local monorepo build)
None of these use @react-native-community/cli. Each workflow builds the
prebuilt dependencies + core XCFrameworks via the existing reusable
prebuild-ios-* workflows, primes both flavor slots, then runs the shared
logic in two committed, locally-runnable scripts:
- scripts/e2e/spm-prime-artifacts.js (lay CI tarballs + hermes into the
--artifacts <dir>/<flavor>/ layout)
- scripts/e2e/spm-ios-e2e.js (scaffold -> spm add --deintegrate
-> xcodebuild, per app)
Triggered manually (workflow_dispatch) and nightly (schedule).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an optional `slices` input to prebuild-ios-dependencies.yml and prebuild-ios-core.yml, driving their build matrix from it. It defaults to the full platform set, so existing callers (test-all.yml, releases) are unchanged. The three SwiftPM iOS e2e workflows only ever compile for the iOS simulator, so they now request `["ios-simulator"]` from both prebuild workflows — cutting the dependencies matrix from 8 slices to 1 and the core matrix from 3 to 1 (per flavor), which is the dominant cost of those e2e runs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- spm-ios-e2e.js: build the execFileSync `env` from process.env's string entries only (process.env is Flow-typed to allow numbers, which the execFileSync `env` option rejects), and omit `env` entirely when there is no override so the child inherits process.env as-is. - Both scripts: suppress the parseArgs [incompatible-type] error with the standard "Natural Inference rollout" $FlowFixMe, matching set-version.js and init-project-e2e.js. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
execFileSync's `env` option is invariantly typed {[string]: string |
number | void}, so neither a plain process.env spread ({[string]: string
| void}) nor a string-only object satisfies it. Build the env object
into a correctly-typed indexer instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cipolleschi
left a comment
There was a problem hiding this comment.
Thanks for hardening our CI. However, I think that we are not quite there. This approach does not follow the patterns we are currently using in CI. I left a few comments to improve this approach.
Addresses review feedback that the original approach did not follow the patterns already used in CI: - The three workflows no longer trigger prebuild-ios-dependencies / prebuild-ios-core themselves. They are workflow_call-only and consume the ReactCore / ReactNativeDependencies artifacts produced elsewhere in the run, the way e2e-ios-templateapp does. The `slices` input added to the two prebuild workflows is reverted. - They are invoked from test-all.yml instead of carrying their own cron. Note this means they run per-PR (gated on should_test_ios) and on pushes to main, not nightly -- test-all.yml has no schedule trigger. They start as continue-on-error so a brand-new lane cannot hard-block unrelated iOS PRs; remove that once it has proven green on main. - The new-app workflow reuses the react-native-package artifact instead of rebuilding the npm package. - Both helper scripts are deleted. Priming the artifact slots needs no new code: download-spm-artifacts.js already accepts tarball overrides via RN_CORE_TARBALL_PATH / RN_DEPS_TARBALL_PATH, so the workflows call `npx react-native spm download` directly, and the new-app case reuses scripts/e2e/init-project-e2e.js --useHelloWorld. Debug and Release run as parallel matrix cells. Each cell stages both flavor slots because `spm add` validates both (it stages both framework trees and selects one via a per-configuration build setting). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks for the review — all five points addressed. 1. Don't re-run the prebuilds. Done. The workflows are 2. Call it from test-all, no cron. Done — three reusable calls modeled on 3. Don't rebuild the npm package. Done. newapp 4. The two scripts. Both deleted. Priming needed no new code: 5. Debug/Release in parallel. They are parallel matrix cells. Each cell does still stage both flavors: |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gins.h (#57697) Summary: rn-tester's `MyNativeView` example imports `RCTFabricComponentsPlugins.h`. The quoted form resolves under CocoaPods (the bare filename is re-vended via `FACADE_REEXPOSED_HEADERS` in `rncore_facades.rb`) and under the internal Meta build (the per-target header generated by buck's `plugins_header`), but not under SwiftPM. Under SwiftPM the header is exposed as an include directory, so only `<React/RCTFabricComponentsPlugins.h>` resolves. The quoted import makes `MyNativeView` fail to compile when rn-tester is converted to SwiftPM (surfaced by the new SPM CI lane in #57659), and switching to the angle form alone would instead break the internal build. The fix uses a `__has_include` conditional: the angle form when it is available (SwiftPM and CocoaPods) with the quoted form as a fallback (the internal build). This matches the existing pattern in rn-tester's own `NativeCxxModuleExample.h` and keeps all three build stacks compiling. ## Changelog: [INTERNAL] [FIXED] - Make rn-tester's NativeComponentExample header import resolve under SwiftPM, CocoaPods and the internal build Pull Request resolved: #57697 Test Plan: - Repro on clean `main`: converting rn-tester to SwiftPM (`spm add --deintegrate`) and building fails at `RNTMyNativeViewComponentView.mm` with `fatal error: 'RCTFabricComponentsPlugins.h' file not found`. - With this change: the same SwiftPM conversion plus `xcodebuild -configuration Debug -sdk iphonesimulator` gives `BUILD SUCCEEDED`. - Internal build: `buck2 build fbsource//xplat/js/react-native-github/packages/rn-tester:NativeComponentExampleApple` succeeds (it takes the quoted fallback). - Existing CocoaPods CI (`test_ios_rntester`) covers the CocoaPods path. Reviewed By: cipolleschi Differential Revision: D113771766 Pulled By: fabriziocucci fbshipit-source-id: e4549508f8e56942b45fa128b2391a290499d4a8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
react-native-xcode.sh already handles this: when there is no Pods installation and the Pods hermesc path does not exist, it resolves the hermes-compiler package through react-native's own dependency graph (scripts/react-native-xcode.sh:83-99). Exporting HERMES_CLI_PATH from the workflow bypassed that shipped resolution, so the Release cells were not exercising what a real SwiftPM consumer does — and a harness-side export of this variable has previously masked hermes VM/compiler bytecode skew. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"Prime SwiftPM artifacts" borrowed jargon from a local test harness and made the step look bespoke. It is the ordinary `spm download`, pointed at the XCFrameworks the prebuild jobs just produced instead of the published nightly. Name it after what it does and say so in the comment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
All six cells (rn-tester, HelloWorld and a fresh app, Debug and Release) passed in run 30379384838, so the lanes no longer need to be advisory. Dropping continue-on-error means a SwiftPM regression fails test-all instead of being reported as a green run with red cells inside it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary:
Adds CI coverage for the SwiftPM (SPM) iOS path, which currently has none. Three standalone workflows scaffold + convert an app to SPM using the prebuilt XCFrameworks and compile it for the iOS simulator:
test-ios-spm-rntester.yml—packages/rn-testertest-ios-spm-helloworld.yml—private/helloworldtest-ios-spm-newapp.yml— a fresh copy ofprivate/helloworld, wired to a Verdaccio-published build of this monorepoNone of them use
@react-native-community/cli. The shared logic lives in two committed, locally-runnable scripts (scripts/e2e/spm-prime-artifacts.js,scripts/e2e/spm-ios-e2e.js); the workflows are thin wrappers. They run manually (workflow_dispatch) and nightly (schedule).This also adds an optional
slicesinput toprebuild-ios-dependencies.ymlandprebuild-ios-core.yml. It defaults to the full platform set, so existing callers (test-all.yml, releases) are unchanged; the e2e workflows request onlyios-simulator, since that is all they compile against.Changelog:
[INTERNAL] [ADDED] - CI workflows validating the SwiftPM iOS build (RNTester, HelloWorld, new app)
Test Plan:
spm add+xcodebuild. Theslicesinput correctly collapsed the prebuild matrices to the singleios-simulatorslice per flavor.node --check,prettier --check, andeslintclean on both scripts; all workflow YAML validated.